
/*
        process.h
        
        Macros, structs and methods used for process switch
        
        Meng Sun(c) leon.meng.sun@gmail.com
        Source code released under LGPLv3
        https://www.gnu.org/licenses/lgpl-3.0.txt
*/

#ifndef ISAMIPS_QEMU_PROCESS
#define ISAMIPS_QEMU_PROCESS

#include "mips32r2.h"
#include "mm.h"

extern uint32 INITSSAVEENVSLOT;

#define MacroSetCurrentASID(u8ASID) \
	asm volatile ( \
		"move $t0, %0 /*t0 is loaded with pd ASID*/ \n\t" \
		"mfc0 $t1, $10, 0 /*t1 is loaded with CP0 EntryHi*/ \n\t" \
		"li $t2, 0xffffff00 \n\t" \
		"and $t1, $t1, $t2 /*clear all ASID bits in t1*/ \n\t" \
		"li $t2, 0x000000ff \n\t" \
		"and $t0, $t0, $t2 /*pre-filter input ASID in t0*/ \n\t" \
		"or $t1, $t1, $t0 /*set 1-s as per pd ASID*/ \n\t" \
		"mtc0 $t1, $10, 0 /*write t1 back to CP0 EntryHi*/ \n\t" \
		: /*no outputs*/ \
		: "r"(u8ASID) \
		: "t0", "t1", "t2" \
	)

#define MacroGetCurrentASID(u8ASID) \
	asm volatile ( \
		"mfc0 $t0, $10, 0 /*load CP0 EntryHi to t0*/ \n\t" \
		"li $t1, 0x000000ff \n\t" \
		"and %0, $t0, $t1 \n\t" \
		: "=r"(u8ASID) \
		: /*no inputs*/ \
		: "t0", "t1" \
	)

#define GETIDXFROMFP(index) ((uint32)(&INITSSAVEENVSLOT) + 4 - 1 - (index))

struct _ProcessDescriptor{

	/*process Description*/
	
	uint8 processID;
	uint8 parentProcessID;
	uint8 originPriority;
	uint8 modifiedPriority;

	/*registry saving block*/
	
	reg32b gpr[31]; /*r1-r31*/
	/*fpu?*/
	reg32b cp0EPC; /*EPC register in CP0*/
	reg32b cp0ErrorPC; /*ErrorPC register in CP0*/
	reg32b cp0Status; /*Status register in CP0*/
	
	/*occupied memory pages*/
	
	MemoryPageDescriptor* mpdListHead;
	
	/*occupied and free dynamic object descriptors*/
	DynamicObjectDescriptor* dodFreeListHead;
	DynamicObjectDescriptor* dodUsedListHead;
	
	/*link list*/
	
	struct _ProcessDescriptor* prev;
	struct _ProcessDescriptor* next;
} ALIGN4B ;

struct _InterProcessMessage{
	uint8 source; /*source process id*/
	uint32 type;
	union {
		
		/*type 1*/
		struct {
			uint32 ui1;
			uint32 ui2;
			uint32 ui3;
			void* vp1;
			void* vp2;
			void* vp3;
		}type1;
		
		/*type 2*/
		struct {
			uint32 ui1;
			uint32 ui2;
			uint32 ui3;
			uint64 ul1;
			uint64 ul2;
			void* vp1;
		}type2;
		
		/*type3*/
		struct {
			uint32 ui1;
			uint32 ui2;
			void* vp1;
			void* vp2;
			unsigned char ca1[64];
		}type3;
		
		/*type4*/
		struct {
			uint32 ui1;
			uint32 ui2;
			sint32 si1;
			sint32 si2;
			uint64 ul1;
			uint64 ul2;
			sint64 sl1;
			sint64 sl2;
			void* vp1;
			void* vp2;
		}type4;
	}payload;
} ALIGN4B ;

typedef struct _InterProcessMessage InterProcessMessage;

typedef struct _ProcessDescriptor ProcessDescriptor;

public sint8 procRemovePDFromList(ProcessDescriptor*, ProcessDescriptor**);

public sint8 procAppendPDToList(ProcessDescriptor*, ProcessDescriptor**);

public sint8 procByteFiller(byte*, uint32, byte);

public sint8 procWordFiller(uint32*, uint32, uint32);

public sint8 procMemoryUnmap(ProcessDescriptor*, MemoryPageDescriptor*);

public MemoryPageDescriptor* procMemoryMap(ProcessDescriptor*, byte*);

public sint8 procPDInit(ProcessDescriptor*, uint8, uint8, uint8);

public sint8 procInit(void);

public ProcessDescriptor* procExecProcessFromMemory(byte*, uint32, uint8, uint8);

public void procScheduler(uint32*);

public sint8 procKillProcess(ProcessDescriptor*, uint32*);

#endif

